import React, { Component, Fragment } from 'react'
import { connect } from 'react-redux'

import cs from 'classnames'
import qs from 'qs'
import store from 'store'
import _ from 'lodash'
import axios from 'axios'
import moment from 'moment'
import { createForm } from 'rc-form'
import { Button } from 'antd'
import { List, InputItem, Picker, Modal, Toast } from 'antd-mobile'
import HeaderLayout from 'layout/header'
import Banner from 'component/banner'
import Card from 'component/card'
import BankBrand from 'component/bankBrand'

import countdown from 'utils/countdown'
import { wait } from 'utils/wait'
import { formatDuring } from 'config/time'
import { formatTitle } from 'config/title'
import { encryptIdcard, encryptPhone, encryptBankcard } from 'config/encrypt'

import { updatePayIndex } from 'model/user'
import { getData } from 'model/dict_bank'


import { valid_phone, valid_bankcard } from 'config/rule'
import { url, api } from 'config/api'

import style from './index.less'

const { Item } = List
const { alert } = Modal

// 获取验证码间隔秒数
const GET_VALID_INTERVAL = 60

@connect(state => ({
  user: state.user,
  building: state.building,
  dict_bank: state.dict_bank,
}), {
  updatePayIndex,
  getData
})
@createForm()
export default class App extends Component {
  isMount = true

  constructor (props) {
    super(props)

    const {
      houseId,
      houseOrderId,
      tradeTime,
      paymentDate,
    } = qs.parse(props.location.search.replace(/^\?/g, ''))

    const {
      user: {
        payIndex
      }
    } = props

    this.state = {
      // 房源id
      houseId,
      // 房源订单id
      houseOrderId,
      // 支付开始时间
      tradeTime,
      // 支付时间 单位 分钟
      paymentDate,

      // 支付倒计时
      payIndex,

      // 是否已同意协议
      isAgree: false,

      // 是否显示银行
      visibleBank: false,
      // 是否显示合同
      visibleContract: false,
      // 是否成功模态框
      visibleSuccess: false,
      // 是否失败模态框
      visibleFail: false,

      // 成功提示文字
      successText: '',
      // 失败提示文字
      failText: '',

      // 当前选择的银行
      selectBank: {},

      // 是否获取过验证码
      isGetValid: false,
      // 是否正在向服务器获取验证码
      getValidLoading: false,
      // 获取验证码计时器
      getValidIndex: GET_VALID_INTERVAL,

      // 是否正在发送绑定银行卡请求
      bindLoading: false,

      // 是否正在支付中
      payLoading: false,

      // 是否已绑定银行卡
      isBind: false,
    }
  }

  componentDidMount () {
    const { tradeTime, paymentDate } = this.state

    // 必须传递的url参数
    const mustArgs = ['houseId', 'houseOrderId', 'tradeTime', 'paymentDate']

    if (!mustArgs.every(v => this.state[v])) {
      Toast.fail('缺少参数', 3, null, false)
      this.props.history.replace('/house/i')

      return
    }

    const _tradeTime = Number(tradeTime)
    const _paymentDate = Number(paymentDate)

    if (_.isNaN(_paymentDate) || _paymentDate < 0) {
      Toast.fail('参数[paymentDate]值错误', 3, null, false)
      this.props.history.replace('/house/i')

      return
    }

    if (!moment(_tradeTime).isValid()) {
      Toast.fail('参数[tradeTime]值错误', 3, null, false)
      this.props.history.replace('/house/i')

      return
    }

    // 支付截止时间和当前系统时间的差值 单位:秒
    const diffS = moment(_tradeTime).add(_paymentDate, 'm').diff(moment(), 's')

    this.setState({ payIndex: diffS })

    // 开始支付开始
    countdown(
      diffS,

      // 同步state
      payIndex => {
        if (this.isMount) {
          this.setState({ payIndex })
        }
      },

      // 超时
      async () => {
        // Toast.fail(`支付时间超时(${ diffS })`, 3, null, false)
        // this.props.history.replace('/house/i')

        this.setState({
          visibleFail: true,
          failText: '支付超时'
        })

        await wait(2)

        this.props.history.push('/house/i?refresh=1')
      }
    )

    this.initData()
  }

  componentWillUnmount () {
    this.isMount = false

    this.props.updatePayIndex(this.state.payIndex)
  }

  // 初始化数据
  initData = async () => {
    this.props.getData()
  }

  // 同意合同
  handleAgree = e => {
    this.setState({
      isAgree: true,
      visibleContract: false,
    })
  }

  // 获取验证码
  handleGetValid = async () => {
    if (this.state.getValidLoading) {
      return
    }

    let query = {}

    {
      const [err, res] = this.valid('mscode')

      if (err) {
        Toast.fail(err, 3, null, false)

        return
      }

      query = res
    }

    Toast.loading('获取验证码中', 0, null, true)
    await this.setState({ getValidLoading: true })

    const [err, res] = await axios.post(url.server + api.pay.sendBindBankcardVCode, query)

    Toast.hide()
    await this.setState({ getValidLoading: false })

    if (err) {
      alert('提示', '验证码获取失败，请重试', [
        { text: '知道了' },
      ])

      return
    }

    this.setState({
      isGetValid: true
    })

    Toast.success('验证码发送成功', 3, null, false)

    // 获取验证码倒计时
    this.getValidTimer = countdown(
      GET_VALID_INTERVAL,

      // 同步state
      getValidIndex => {
        if (this.isMount) {
          this.setState({ getValidIndex })
        }
      },

      () => {
        if (this.isMount) {
          this.setState({
            getValidIndex: GET_VALID_INTERVAL,
          })
        }
      }
    )

    // 获取验证码倒计时
  }

  // 绑定银行卡
  handleBind = async (code) => {
    if (this.state.bindLoading) {
      return
    }

    let query = {}

    {
      const [err, res] = this.valid(null, true)

      if (err) {
        Toast.fail(err, 3, null, false)

        return
      }

      query = res
    }

    Toast.loading('绑定银行卡中', 0, null, true)
    await this.setState({ bindLoading: true })

    const [err, res] = await axios.post(url.server + api.pay.bindBankcard, query)

    Toast.hide()
    await this.setState({ bindLoading: false })

    if (err) {
      alert('提示', err, [
        { text: '知道了' },
      ])

      return
    }

    this.setState({
      isBind: true,
      visibleSuccess: true,
      successText: '绑定银行卡成功'
    })

    await wait(2)

    this.setState({
      visibleSuccess: false
    })
  }

  // 支付
  handlePay = async () => {
    const {
      houseOrderId,
      payLoading,
    } = this.state

    if (payLoading) {
      return
    }

    Toast.loading('支付中', 0, null, true)
    await this.setState({ payLoading: true })
    const Authorization = store.get('token')
    const [err, res] = await axios.post(url.server + api.pay.submit, {
      houseOrderId,
      Authorization
    })

    Toast.hide()
    await this.setState({ payLoading: false })

    if (err) {
      // alert('提示', err, [
      //   { text: '知道了' },
      // ])
      this.setState({
        visibleFail: true,
        failText: err,

        // 重置一些状态
        isAgree: false,
        isBind: false,
        isGetValid: false,
        getValidIndex: GET_VALID_INTERVAL,
        selectBank: {}
      })

      // 重置表单
      this.props.form.resetFields()
      // 重置获取验证码计时器
      clearInterval(this.getValidTimer)
      this.getValidTimer = null

      await wait(2)

      this.setState({
        visibleFail: false
      })

      return
    }

    const {
      data: {
        msg,
        /**
         * [Number] 状态码
         *   0: 支付成功
         *   1: 支付失败
         *   2: 支付超时
         */
        state
      } = {}
    } = res

    // 支付失败
    // 支付失败服务器会自动解绑银行卡
    // 需要重新绑定银行卡
    if (state !== 0) {
      this.setState({
        visibleFail: true,
        failText: state === 2 ? '支付超时' : '支付失败',

        // 重置一些状态
        isAgree: false,
        isBind: false,
        isGetValid: false,
        getValidIndex: GET_VALID_INTERVAL,
        selectBank: {}
      })

      this.props.form.resetFields()
      // 重置获取验证码计时器
      clearInterval(this.getValidTimer)
      this.getValidTimer = null

      await wait(2)

      this.setState({
        visibleFail: false
      })
    }

    // 支付成功后跳转到[我的房源]页面,且刷新我的房源数据
    this.setState({
      visibleSuccess: true,
      successText: '支付成功'
    })

    await wait(2)

    this.props.history.push('/house/i?refresh=1')
  }

  /**
   * [校验表单]
   * @param  {String|String Array} omit       [排除的校验的字段]
   * @param  {Boolean}             isSubmit   [是否是提交绑定]
   * @return {[err, res]}
   */
  valid = (omit, isSubmit) => {
    const {
      isAgree,
      isGetValid,
      selectBank,
      houseOrderId,
    } = this.state

    const {
      form: {
        validateFields,
        getFieldsError,
        getFieldsValue,
      }
    } = this.props

    validateFields()

    const error = _.flatMap(getFieldsError(_.without(['bankCardNo', 'phone', 'mscode'], omit))).filter(v => v)

    if (!selectBank.code) {
      error.push('请选择银行')
    }

    if (isSubmit && !isAgree) {
      error.push('请同意协议')
    }

    if (isSubmit && !isGetValid) {
      error.push('请先获取验证码')
    }

    if (error.length) {
      return [error[0]]
    }

    return [null, {
      bankCode: selectBank.code,
      houseOrderId,
      ...getFieldsValue()
    }]
  }

  render () {
    const {
      houseId,

      payIndex,

      visibleBank,
      visibleContract,
      visibleSuccess,
      visibleFail,

      successText,
      failText,

      isAgree,
      selectBank,

      getValidIndex,

      isBind
    } = this.state

    const {
      user: {
        lockHouse
      },
      building: {
        propertyName
      },
      dict_bank,
      form: {
        getFieldProps,
        getFieldValue,
      }
    } = this.props

    const data = lockHouse.find(v => v.houseId === houseId) || {
      housePreiodName: '',
      buildNumName: '',
      floor: '',
      householdNo: '',

      stationaryMoney: '',
      houseOrderId: '',

      realName: '',
      idCardNo: '',
    }

    const title = formatTitle({
      propertyName,
      housePreiodName: data.housePreiodName,
      buildNumName: data.buildNumName,
      floor: data.floor,
      householdNo: data.householdNo,
    })

    const houseData = {
      定金金额: data.stationaryMoney,
      订单编号: data.houseOrderId,
    }

    const userData = {
      客户姓名: data.realName,
      身份证号码: encryptIdcard(data.idCardNo)
    }

    const bankcardData = {
      银行卡号: `${ encryptBankcard(getFieldValue('bankCardNo')) }(${ selectBank.name })`,
      手机号: encryptPhone(getFieldValue('phone'))
    }

    const payData = {
      支付金额: <span className = { style['money'] }>{ data.stationaryMoney }</span>
    }

    return (
      <HeaderLayout
        title = '支付'
        transparent = { true }

        fixed
      >
        <Banner
          label = '支付时间'
          value = { formatDuring(payIndex, 1000) }
        />
        <div className = { style['content'] }>
          <Card
            title = { title }
            data = { houseData }
          />
          <Card
            title = '购房人信息'
            data = { userData }
          />
          <Card
            title = '银行卡信息'
            visible = { !isBind }
          >
            <List>
              <Item
                arrow = 'horizontal'
                disabled = { dict_bank.loading }
                onClick = { () => { !dict_bank.loading && this.setState({ visibleBank: true }) } }
              >
                {
                  dict_bank.loading ?
                    '加载中' :
                    selectBank.name ?
                      selectBank.name :
                      '请选择银行卡'
                }
              </Item>
              <InputItem
                {
                ...getFieldProps('bankCardNo', {
                  initialValue: '',
                  // initialValue: '6217711202066336',
                  rules: valid_bankcard()
                })
                }
                placeholder = '请输入购房人银行卡号'
              />
              <InputItem
                {
                ...getFieldProps('phone', {
                  initialValue: '',
                  // initialValue: '15870448346',
                  rules: valid_phone()
                })
                }
                placeholder = '输入银行卡预留手机号'
              />
              <InputItem
                {
                ...getFieldProps('mscode', {
                  initialValue: '',
                  // initialValue: '123456',
                  rules: [{
                    required: true,
                    message: '请输入验证码'
                  }]
                })
                }
                extra = {
                  getValidIndex >= GET_VALID_INTERVAL ?
                    <span className = { style['get-valid'] } onClick = { this.handleGetValid }>获取验证码</span> :
                    <span>{ getValidIndex }</span>
                }
                placeholder = '输入验证码'
              />
              <div
                className = {
                  cs(style['agree'], {
                    [style['agree-active']]: isAgree
                  })
                }

                onClick = { () => this.setState(prevState => ({ isAgree: !prevState.isAgree })) }
              >
                <i />
                <span>
                  阅读并已确认
                  <a
                    onClick = {
                      e => {
                        e.stopPropagation()

                        this.setState({ visibleContract: true })
                      }
                    }
                  >
                    《在线支付协议》
                  </a>
                </span>
              </div>
            </List>
          </Card>
          {
            isBind ?
              <Fragment>
                <Card
                  title = '银行卡信息'
                  data = { bankcardData }
                />
                <Card
                  data = { payData }
                />
              </Fragment> :
              null
          }
          {
            isBind ?
              <Button onClick = { this.handlePay } block type = 'primary' size = 'large'>确定支付</Button> :
              <Button onClick = { this.handleBind } block type = 'primary' size = 'large'>确定</Button>
          }
        </div>

        <Modal
          visible = { visibleBank }
          onClose = { () => this.setState({ visibleBank: false }) }
          animationType = 'slide-up'
          className = { style['bank-modal'] }
          popup
        >
          <div className = { style['bank'] }>
            <div className = { style['modal-header'] }>
              <h2>请选择银行</h2>
              <a
                className = { style['modal-close'] }
                onClick = { () => this.setState({ visibleBank: false }) }
              />
            </div>
            <div className = { style['bank-body'] }>
              {
                dict_bank.data.map((v, i) => (
                  <Bank
                    { ...v }

                    onChange = { () => this.setState({ selectBank: v, visibleBank: false }) }
                    checked = { v.id === selectBank.id }

                    key = { i }
                  />
                ))
              }
            </div>
          </div>
        </Modal>

        <Modal
          visible = { visibleContract }
          onClose = { () => this.setState({ visibleContract: false }) }
          animationType = 'slide-up'
          className = { style['contract-modal'] }
          popup
        >
          <div className = { style['contract'] }>
            <div className = { style['modal-header'] }>
              <h2>壹房通支付协议</h2>
              <a
                className = { style['modal-close'] }
                onClick = { () => this.setState({ visibleContract: false }) }
              />
            </div>
            <div className = { style['contract-body'] }></div>
            <div className = { style['contract-footer'] }>
              <Button onClick = { this.handleAgree } block type = 'primary' size = 'large'>阅读并确认</Button>
            </div>
          </div>
        </Modal>

        <Modal
          visible = { visibleSuccess }
          // onClose = { () => this.setState({ visibleSuccess: false }) }
          transparent
          className = { style['result-modal'] }
        >
          <i className = { cs(style['result-modal-legend'], style['result-modal-legend-success']) } />
          <p>{ successText }</p>
        </Modal>

        <Modal
          visible = { visibleFail }
          // onClose = { () => this.setState({ visibleFail: false }) }
          transparent
          className = { style['result-modal'] }
        >
          <i className = { cs(style['result-modal-legend'], style['result-modal-legend-fail']) } />
          <p>{ failText }</p>
        </Modal>
      </HeaderLayout>
    )
  }
}

const Bank = ({ name, type = '储蓄卡', checked, code, onChange = f => f }) => {
  return (
    <div
      className = { style['bank-checkbox'] }
      onClick = { () => {
        if (!checked) {
          onChange()
        }
      } }
    >
      <div className = { style['bank-checkbox-before'] }>
        <BankBrand type = { code } />
      </div>
      <div className = { style['bank-checkbox-content'] }>
        <h2>{ name }</h2>
        <p>{ type }</p>
      </div>
      <div className = { style['bank-checkbox-after'] }>
        {
          checked ?
            <div className = { style['checkbox'] } /> :
            null
        }
      </div>
    </div>
  )
}
